package org.dreamwork.jasmine2.editor;

import org.dreamwork.jasmine2.engine.JasmineRequest;
import org.dreamwork.misc.Base64;
import org.dreamwork.util.FileInfo;
import org.dreamwork.util.StringUtil;
import org.dreamwork.util.VirtualFile;

import javax.imageio.ImageIO;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Pattern;

/**
 * Created by IntelliJ IDEA.
 * User: seth.yang
 * Date: 12-7-9
 * Time: 下午3:15
 */
public class UploadServlet extends HttpServlet {
    private static final SimpleDateFormat sdf = new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss");

    @Override
    @SuppressWarnings ("unchecked")
    protected void doPost (HttpServletRequest req, HttpServletResponse response) throws ServletException, IOException {
        ServletContext context = getServletContext ();
        JasmineRequest request = new JasmineRequest (req);
        String folderName = request.getParameter ("folderName");
        folderName = translatePath (folderName, request.getSession ());
        VirtualFile vf = request.getVirtualFile ("file");
        try {
            Map<String, String> mappings = (Map<String, String>) context.getAttribute (EditorResourceServlet.MAPPING_CONTEXT_KEY);
            String prefix = mappings.get ("user-upload");
            URL url = new URL (prefix);
            File base = new File (url.getFile ());
            if (!base.exists () && !base.mkdirs ())
                throw new IOException ("Can't create folder: " + base.getCanonicalPath ());
            String ext = FileInfo.getExtension (vf.getName ());
            String fileName = FileInfo.getFileNameWithoutExtension (vf.getName ());
            byte[] data = Base64.encode (fileName.getBytes ("UTF-8"));
            fileName = new String (data, "UTF-8");
            File file = new File (base, folderName + '/' + fileName + '.' + ext);
            vf.saveAs (file.getCanonicalPath ());

            String target = request.getContextPath () + "/browser/post-upload.html";
            response.sendRedirect (target);
        } catch (Exception ex) {
            throw new ServletException (ex);
        }
    }

    @Override

    protected void doGet (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String action = request.getParameter ("a");
        if ("create-folder".equalsIgnoreCase (action)) {
            createFolder (request, response);
        } else if ("image-list".equalsIgnoreCase (action)) {
            getImageList (request, response);
        }
    }

    @SuppressWarnings ("unchecked")
    private void getImageList (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        ServletContext context = getServletContext ();
        String path = request.getParameter ("path");
        if (StringUtil.isEmpty (path)) path = "public";

        path = translatePath (path, request.getSession ());
        Map<String, String> mappings = (Map<String, String>) context.getAttribute (EditorResourceServlet.MAPPING_CONTEXT_KEY);
        String prefix = mappings.get ("user-upload");
        URL url = new URL (prefix);
        File base = new File (url.getFile ());
        if (!base.exists ()) {
            response.sendError (HttpServletResponse.SC_NOT_FOUND);
            response.flushBuffer ();
            return;
        }

        String pathInfo = request.getContextPath () + "/user-upload/" + path;

        File folder = new File (base, path);
        StringBuilder builder = new StringBuilder ();
        int index = 0;

        File[] files = folder.listFiles (folderFilter);
        if (files != null) for (File file : files) {
            if (index != 0) builder.append (',');
            builder.append ("{name:'").append (file.getName ()).append ("', type:'folder'}");
            index ++;
        }
        files = folder.listFiles (filter);
        if (files != null) for (File file : files) {
            String fullPath = file.getCanonicalPath ();
            String fileName = FileInfo.getFileNameWithoutExtension (fullPath);
            String name = new String (Base64.decode (fileName), "UTF-8");
            String ext = FileInfo.getExtension (fullPath);
            String src = pathInfo + '/' + fileName + '.' + ext;
            src = src.replace (File.separatorChar, '/');
            BufferedImage image = ImageIO.read (file);
            if (index != 0) builder.append (',');
            builder.append ("{name:'").append (name).append ('.').append (ext).append ("',type:'")
                    .append (FileInfo.getMimeType (fullPath).getName ()).append ("',lastModify:'")
                    .append (sdf.format (new Date (file.lastModified ()))).append ("',width:")
                    .append (image.getWidth ()).append (",height:").append (image.getHeight ())
                    .append (",src:'").append (src).append ("'}");
            index ++;
        }
        response.setContentType ("text/plain;charset=utf-8");
        response.getWriter ().write ("[" + builder + "]");
        response.getWriter ().flush ();
        response.flushBuffer ();
    }

    @SuppressWarnings ("unchecked")
    private void createFolder (HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
        ServletContext context = getServletContext ();
        Map<String, String> mappings = (Map<String, String>) context.getAttribute (EditorResourceServlet.MAPPING_CONTEXT_KEY);
        String prefix = mappings.get ("user-upload");
        URL url = new URL (prefix);
        File base = new File (url.getFile ());
        if (!base.exists ()) {
            response.sendError (HttpServletResponse.SC_NOT_FOUND);
            response.flushBuffer ();
            return;
        }

        String name = request.getParameter ("folderName");
        name = translatePath (name, request.getSession ());
        File file = new File (base, name);

        response.setContentType ("text/plain;charset=utf-8");
        if (file.exists ()) {
            response.getWriter ().write ("{status:'ok'}");
        } else if (file.mkdirs ()) {
            response.getWriter ().write ("{status:'ok'}");
        } else {
            response.getWriter ().write ("{status:'fail'}");
        }
        response.getWriter ().flush ();
        response.flushBuffer ();
    }

    private String translatePath (String path, HttpSession session) throws ServletException, IOException {
        String[] array = path.split ("/");
        if (array.length == 0) return path;

        if ("private".equalsIgnoreCase (array [0])) {
            ServletContext context = getServletContext ();
            IPrivateFolderFetcher fetcher = (IPrivateFolderFetcher) context.getAttribute (EditorResourceServlet.RESOURCE_FETCHER_FACTORY);
            if (fetcher == null) {
                throw new ServletException ("");
            }

            array [0] = fetcher.getPrivateFolderName (session);
            StringBuilder builder = new StringBuilder ();
            for (String part : array) {
                if (builder.length () > 0) builder.append ('/');
                builder.append (part);
            }
            return builder.toString ();
        }
        return path;
    }

    private static FileFilter filter = new FileFilter () {
        private final Pattern p = Pattern.compile ("jpg|jpeg|png|gif", Pattern.CASE_INSENSITIVE);
        public boolean accept (File file) {
            if (file.isDirectory ())  return false;
            String ext = FileInfo.getExtension (file.getName ());
            return p.matcher (ext).matches ();
        }
    };

    private static FileFilter folderFilter = new FileFilter () {
        @Override
        public boolean accept (File file) {
            return file.isDirectory ();
        }
    };
}